home *** CD-ROM | disk | FTP | other *** search
- #include <dos.h>
- #include <conio.h>
- #include <string.h>
-
- #include "misc.hpp"
- #include "screen.hpp"
- #include "vgalib.hpp"
-
-
- GraphicsAPI::GraphicsAPI(int xr, int yr, int vxr, int vyr, int clrs)
- {
- int segm, offs;
- xres = xr;
- yres = yr;
- vxres = vxr;
- vyres = vyr;
- colors = clrs;
- libID = "Generic Graphics";
- asm {
- push bp
- mov ax, 1130h
- mov bh, 03h
- int 10h
- mov ax, bp
- pop bp
- mov [segm], es
- mov [offs], ax
- }
- font = (unsigned char *)MK_FP(segm, offs);
- fontHeight = fontWidth = 8;
- }
-
- void GraphicsAPI::hLine(int x, int y, int l)
- {
- while (l--)
- putPixel(x++, y);
- }
-
- void GraphicsAPI::vLine(int x, int y, int l)
- {
- while (l--)
- putPixel(x, y++);
- }
-
- /*
- * Generic line drawing routine, using Bresenham's algorithm.
- * Taken from Richard Wilton: "PC & PS/2 Video Systems" p. 166-7
- */
-
- void GraphicsAPI::line(int x1, int y1, int x2, int y2)
- {
- if (x1==x2)
- {
- sort(y1, y2);
- vLine(x1, y1, y2-y1+1);
- return;
- }
- if (y1==y2)
- {
- sort(x1, x2);
- hLine(x1, y1, x2-x1+1);
- }
- int dx = absolute(x2-x1);
- int dy = absolute(y2-y1);
- if (dx >= dy)
- {
- if (x1>x2)
- {
- swap(x1, x2);
- swap(y1, y2);
- }
- int yincr = 1;
- if (y2<y1)
- yincr = -yincr;
- int d = 2 * dy - dx;
- int aincr = 2 * (dy - dx);
- int bincr = 2 * dy;
- int x = x1;
- int y = y1;
- putPixel(x, y);
- while (++x <= x2)
- {
- if (d >= 0)
- {
- y += yincr;
- d += aincr;
- }
- else
- d += bincr;
- putPixel(x, y);
- }
- }
- else
- {
- if (y1>y2)
- {
- swap(x1, x2);
- swap(y1, y2);
- }
- int xincr = 1;
- if (x2<x1)
- xincr = -xincr;
- int d = 2*dx - dy;
- int aincr = 2 * (dx - dy);
- int bincr = 2 * dx;
- int x = x1;
- int y = y1;
- putPixel(x, y);
- while (++y <= y2)
- {
- if (d >= 0)
- {
- x += xincr;
- d += aincr;
- }
- else
- d += bincr;
- putPixel(x, y);
- }
- }
- }
-
- void GraphicsAPI::rectangle(int x1, int y1, int x2, int y2)
- {
- sort(x1, x2);
- sort(y1, y2);
- hLine(x1, y1, x2-x1);
- hLine(x1, y2, x2-x1);
- vLine(x1, y1, y2-y1);
- vLine(x2, y1, y2-y1);
- }
-
- void GraphicsAPI::bar(int x1, int y1, int x2, int y2)
- {
- int width = x2-x1+1;
- for (int y = y1; y < y2; ++y)
- hLine(x1, y, width);
- }
-
- void GraphicsAPI::wipe()
- {
- bar(0, 0, vxres, vyres);
- }
-
- void GraphicsAPI::putChar(int x, int y, int ch)
- {
- unsigned char *fptr = font + fontHeight*ch;
- for (int j=0; j<fontHeight; ++j, ++fptr)
- {
- char mask = *fptr;
- for (int i=0; i<fontWidth; ++i)
- {
- asm shl [mask], 1;
- asm jnc skip
- putPixel(x+i, y+j, color);
- skip:
- }
- }
- }
-
- void GraphicsAPI::putText(int x, int y, char *txt)
- {
- switch (hJustify)
- {
- case HCENTER:
- x -= fontWidth * strlen(txt) / 2;
- break;
- case RIGHT:
- x -= fontWidth * strlen(txt);
- break;
- }
- switch (vJustify)
- {
- case VCENTER:
- y -= fontHeight / 2;
- break;
- case BOTTOM:
- y -= fontHeight;
- break;
- }
-
- while (*txt)
- {
- putChar(x, y, *(txt++));
- x += fontWidth;
- }
- }
-
- void GraphicsAPI::setTextJustify(HJustify h, VJustify v)
- {
- hJustify = h;
- vJustify = v;
- }
-
-
- /*
- * VGAGraphicsAPI
- */
-
- unsigned char *VGAGraphicsAPI::videoBuf =
- (unsigned char *)MK_FP(0xa000,0);
-
- VGAGraphicsAPI::VGAGraphicsAPI(int xr, int yr, int vxr, int xb, int clrs)
- : GraphicsAPI(xr, yr, vxr, 65536L/xb, clrs), xbytes(xb)
- {
- libID = "VGA Graphics";
- outp(0x3ce, 0x05);
- int t = inp(0x3cf);
- outpw(0x3ce, 0x05 | (t & 0xfc) << 8); // write mode 0
- outpw(0x3c4, 0x0f02); // enable all planes
- }
-
-
- void VGAGraphicsAPI::syncWithRefresh()
- {
- while (inp(0x3da)&0x8);
- while (!(inp(0x3da)&0x8));
- }
-
- unsigned VGAGraphicsAPI::getOffset(int x, int y)
- {
- return y * xbytes + x/(vxres/xbytes);
- }
-
- void VGAGraphicsAPI::setBase(int x=0, int y=0)
- {
- unsigned offset = getOffset(x,y);
- inp(0x3da);
- outp(0x3c0, 0x33);
- outp(0x3c0, getPelPan(x));
- outpw(0x3d4, 0x0c | (offset & 0xff00));
- outpw(0x3d4, 0x0d | (offset & 0x00ff)<<8);
- syncWithRefresh();
- }
-
-
- /*
- * Planar16
- */
-
- Planar16::Planar16(int xr, int yr, int vxr)
- : VGAGraphicsAPI(xr, yr, vxr, vxr>>3, 16)
- {
- libID = "4-plane 16-color mode";
- outpw(0x3ce, 0x0f01); // enable set/reset
- }
-
- void Planar16::putPixel(int x, int y, int c)
- {
- outpw(0x3ce, 0x00 | (c<<8)); // set/reset to select color
- outpw(0x3ce, 0x08 | 0x8000>>(x&7)); // bit mask to select bit
- unsigned char *pos = graphScr+y*xbytes+(x>>3);
- *pos = *pos;
- }
-
- int Planar16::getPixel(int x, int y)
- {
- return videoBuf[y*xbytes+x];
- }
-
- void Planar16::hLine(int x, int y, int l)
- {
- outpw(0x3ce, 0x00 | (color<<8)); // set/reset to select color
- unsigned char *pos = graphScr+y*xbytes+(x>>3);
- int mask;
- int shift = x & 7;
- if (shift > 0)
- {
- mask = 0x00ff >> shift;
- l -= 8 - shift;
- if (l<0)
- mask &= 0xff << -l;
- outpw(0x3ce, 0x08 | mask << 8); // bit mask to select first bits
- *pos = *pos;
- ++pos;
- }
- if (l >= 8)
- {
- outpw(0x3ce, 0xff08); // bit mask to select 8 bits
- memset(pos, 0, l>>3);
- pos += l>>3;
- l -= l & 0xf8;
- }
- if (l >= 0)
- {
- mask = 0xff00 << (8-l);
- outpw(0x3ce, 0x08 | mask); // bit mask to select last bits
- *pos = *pos;
- }
- }
-
- int Planar16::getPelPan(int x)
- {
- return x & 7;
- }
-
- /*
- * Chained256
- */
-
- Chained256::Chained256(int xr, int yr, int vxr)
- : VGAGraphicsAPI(xr, yr, vxr, vxr, 256)
- {
- libID = "Chained 256-color mode";
- }
-
- void Chained256::putPixel(int x, int y, int c)
- {
- videoBuf[y*xbytes+x] = c;
- }
-
- int Chained256::getPixel(int x, int y)
- {
- return videoBuf[y*xbytes+x];
- }
-
- void Chained256::hLine(int x, int y, int l)
- {
- memset(graphScr+y*xbytes+x, color, l);
- }
-
- unsigned Chained256::getOffset(int x, int y)
- {
- return (y * xbytes + x/(vxres/xbytes)) >> 2;
- }
-
- int Chained256::getPelPan(int x)
- {
- return 2*(x & 3);
- }
-
-
- /*
- * Unchained256
- */
-
- Unchained256::Unchained256(int xr, int yr, int vxr)
- : VGAGraphicsAPI(xr, yr, vxr, vxr>>2, 256)
- {
- libID = "Unchained 256-color mode";
- }
-
- void Unchained256::putPixel(int x, int y, int c)
- {
- outpw(0x3c4, 0x02 | 0x0100<<(x&3));
- videoBuf[y*xbytes+(x>>2)] = c;
- }
-
- int Unchained256::getPixel(int x, int y)
- {
- return videoBuf[y*xbytes+x];
- }
-
- void Unchained256::hLine(int x, int y, int l)
- {
- unsigned char *pos = graphScr+y*xbytes+(x>>2);
- int mask;
- int shift = x & 3;
- if (shift > 0)
- {
- mask = 0x000f << shift & 0x000f;
- l -= 4-shift;
- if (l<0)
- mask &= 0x0f >> -l;
- outpw(0x3c4, 0x02 | mask << 8); // write enable first pixels
- *(pos++) = color;
- }
- if (l >= 4)
- {
- outpw(0x3c4, 0x0f02); // write enable 4 pixels
- memset(pos, color, l>>2);
- pos += l>>2;
- l -= l & 0xfc;
- }
- if (l >= 0)
- {
- mask = 0x0f00 >> (4-l) & 0x0f00;
- outpw(0x3c4, 0x02 | mask); // write enable last pixels
- *pos = color;
- }
- }
-
- int Unchained256::getPelPan(int x)
- {
- return 2*(x & 3);
- }
-